home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1998 October
/
EnigmA AMIGA RUN 31 (1998)(G.R. Edizioni)(IT)[!][issue 1998-10].iso
/
linux
/
ppmtoagafb-0.7
/
encodeham8.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-09-22
|
4KB
|
155 lines
/* HAM8 encoding, based on the jpegAGA HAM8 encoding
* Originally by Günther Röhrich
* Converted to C by Chris Lawrence <quango@themall.net>
*
* (©) Copyright 1996-97 by Chris Lawrence
*
* This file is subject to the terms and conditions of the GNU General Public
* License. See the file COPYING in the main directory of the Linux
* distribution for more details.
*
* To do: translate this into human-readable C
* (as opposed to assembleresque C).
* gcc might then be able to optimize it decently.
*/
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include "ppm.h"
extern u_char ColorTable[64 * 3], *ColorCache;
extern u_short Mult_Table[256 * 2];
static u_short compute_error(u_char * orig, u_char * chosen);
void EncodeHAM8(pixel * pixrow, pixval maxval, u_char * yham, u_short xsize,
int do_histogram);
static u_short compute_error(u_char * orig, u_char * chosen)
{
u_short ret, x;
x = abs(orig[0] - chosen[0]);
ret = Mult_Table[x];
x = abs(orig[1] - chosen[1]);
ret += Mult_Table[x];
x = abs(orig[2] - chosen[2]);
ret += Mult_Table[x];
return ret;
}
void EncodeHAM8(pixel * pixrow, pixval maxval, u_char * yham, u_short xsize,
int do_histogram)
{
u_char orig_cols[3], left[3], cache, *finham;
u_char best_color = 3, colcount = 0, ham_offset, tmp, tmp2, change_val;
u_long CacheOffset, offset;
u_short err, min_error;
pixel p;
memcpy(left, ColorTable, sizeof(left));
for( finham = (yham + xsize - 1); yham <= finham; )
{
PPM_DEPTH(p, (*pixrow), maxval, 63);
pixrow++;
orig_cols[0] = PPM_GETB(p);
orig_cols[1] = PPM_GETR(p);
orig_cols[2] = PPM_GETG(p);
if( left[0] != orig_cols[0] || left[1] != orig_cols[1] ||
left[2] != orig_cols[2] )
{
min_error = 65535;
offset = (orig_cols[1] << 12) | (orig_cols[2] << 6) | orig_cols[0];
cache = ColorCache[offset];
if (!cache)
{
CacheOffset = offset;
best_color = offset = 0;
do
{
err = compute_error(orig_cols, &ColorTable[offset]);
offset += 3;
if (err < min_error)
{
min_error = err;
best_color = offset;
}
}
while (err > 0 && offset < 192);
if (err)
{
ColorCache[CacheOffset] = best_color;
}
else
{
min_error = compute_error(orig_cols, &ColorTable[offset - 3]);
}
}
else
{
if (!do_histogram)
{
*(yham++) = ((cache / 3) - 1) << 2;
memcpy(left, &ColorTable[best_color - 3], sizeof(left));
continue;
}
best_color = cache;
min_error = compute_error(orig_cols, &ColorTable[best_color - 3]);
}
change_val = orig_cols[0];
tmp2 = abs(orig_cols[0] - left[0]);
ham_offset = 0;
tmp = abs(orig_cols[1] - left[1]);
if (tmp > tmp2)
{
change_val = orig_cols[1];
ham_offset = 1;
tmp2 = tmp;
}
tmp = abs(orig_cols[2] - left[2]);
if (tmp > tmp2)
{
change_val = orig_cols[2];
ham_offset = 2;
}
tmp = left[ham_offset];
left[ham_offset] = change_val;
err = compute_error(orig_cols, left);
if (min_error >= err)
{
/* Use HAM */
*(yham++) = (change_val << 2) | (ham_offset + 1);
}
else
{
*(yham++) = ((best_color / 3) - 1) << 2;
memcpy(left, &ColorTable[best_color - 3], sizeof(left));
}
}
else
{
ham_offset = colcount;
colcount = (colcount + 1) % 3;
left[ham_offset] = orig_cols[ham_offset];
*(yham++) = (orig_cols[ham_offset] << 2) | (ham_offset + 1);
}
}
return;
}